<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Pyodide Bar Chart Demo (pandas + matplotlib)</title>
    <style>
      :root {
        --bg: #0b1020;
        --card: #111831;
        --text: #e7ecff;
        --muted: #a9b3d2;
        --accent: #7da6ff;
      }
      html, body { height: 100%; }
      body {
        margin: 0; font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Inter, "Helvetica Neue", Arial, Noto Sans, "Apple Color Emoji", "Segoe UI Emoji";
        background: radial-gradient(1200px 600px at 10% -10%, #1b254a 0, transparent 60%),
                    radial-gradient(900px 600px at 100% 0%, #182143 0, transparent 60%),
                    var(--bg);
        color: var(--text);
      }
      .wrap { max-width: 900px; margin: 0 auto; padding: 32px 16px 60px; }
      header { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
      header .dot { width: 10px; height: 10px; border-radius: 999px; background: var(--accent); box-shadow: 0 0 16px var(--accent); }
      h1 { font-size: clamp(22px, 3.2vw, 34px); margin: 0; letter-spacing: 0.2px; }
      p.lead { color: var(--muted); margin: 6px 0 22px; }
      .card {
        background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.02));
        border: 1px solid rgba(255,255,255,0.08);
        border-radius: 18px; padding: 18px; box-shadow: 0 6px 24px rgba(0,0,0,0.25);
      }
      .row { display: grid; grid-template-columns: 1fr; gap: 18px; }
      @media (min-width: 920px){ .row { grid-template-columns: 360px 1fr; } }

      .status { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; font-size: 14px; line-height: 1.4; color: var(--muted); white-space: pre-wrap; }
      .badge { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px; border: 1px solid rgba(255,255,255,0.12); background: rgba(0,0,0,0.2); }
      .spinner { width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.2); border-top-color: var(--accent); border-radius: 50%; animation: spin 1s linear infinite; }
      @keyframes spin { to { transform: rotate(360deg); } }
      .imgwrap { display: grid; place-items: center; min-height: 420px; background: var(--card); border-radius: 14px; border: 1px dashed rgba(255,255,255,0.12); }
      img { max-width: 100%; height: auto; display: block; border-radius: 10px; }
      .footnote { font-size: 12px; color: var(--muted); margin-top: 10px; }
      .btn {
        appearance: none; border: 1px solid rgba(255,255,255,0.14); color: var(--text); background: rgba(125,166,255,0.12);
        padding: 10px 14px; border-radius: 12px; cursor: pointer; font-weight: 600; letter-spacing: .2px; transition: transform .08s ease, background .2s ease;
      }
      .btn:hover { background: rgba(125,166,255,0.18); }
      .btn:active { transform: translateY(1px); }
    </style>
  </head>
  <body>
    <div class="wrap">
      <header>
        <span class="dot"></span>
        <h1>Pyodide + pandas + matplotlib — Bar Chart</h1>
      </header>
      <p class="lead">This page loads <strong>Pyodide</strong> in the browser, uses <strong>pandas</strong> to prep some data, renders a bar chart with <strong>matplotlib</strong>, and displays it below — all client-side.</p>

      <div class="row">
        <div class="card">
          <div class="badge"><span class="spinner" id="spinner"></span><span id="phase">Loading Python runtime…</span></div>
          <pre class="status" id="status"></pre>
          <div style="display:flex; gap:10px; margin-top:10px;">
            <button id="rerun" class="btn" disabled>Re-run demo</button>
            <button id="showcode" class="btn">Show Python</button>
          </div>
          <pre class="status" id="pycode" style="display:none; margin-top:10px;"></pre>
          <div class="footnote">CDN: pyodide, pandas, numpy, matplotlib are fetched on demand. First run may take a few seconds.</div>
        </div>
        <div class="imgwrap card">
          <img id="plot" alt="Bar chart will render here" />
        </div>
      </div>
    </div>

    <!-- Pyodide runtime -->
    <script src="https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js"></script>
    <script>
      const statusEl = document.getElementById('status');
      const phaseEl = document.getElementById('phase');
      const spinnerEl = document.getElementById('spinner');
      const rerunBtn = document.getElementById('rerun');
      const showBtn = document.getElementById('showcode');
      const codeEl = document.getElementById('pycode');

      const PY_CODE = `import pandas as pd
import numpy as np
import matplotlib
matplotlib.use("agg")
import matplotlib.pyplot as plt
from js import document
import io, base64

# --- Sample data with pandas ---
np.random.seed(0)
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
plays = (100 + np.random.randint(-20, 30, size=len(months))).tolist()
frame = pd.DataFrame({"Month": months, "Plays": plays})

# --- Matplotlib bar chart ---
fig, ax = plt.subplots(figsize=(6, 4), dpi=150)
ax.bar(frame["Month"], frame["Plays"])
ax.set_title("Example Bar Chart (pandas + matplotlib in Pyodide)")
ax.set_xlabel("Month")
ax.set_ylabel("Streams")
ax.grid(axis="y", linestyle=":", alpha=0.5)
fig.tight_layout()

# --- Render to PNG and inject into page ---
buf = io.BytesIO()
fig.savefig(buf, format="png")
buf.seek(0)
img_b64 = base64.b64encode(buf.getvalue()).decode("ascii")
document.getElementById("plot").src = "data:image/png;base64," + img_b64
`;

      showBtn.addEventListener('click', () => {
        const visible = codeEl.style.display !== 'none';
        if (visible) {
          codeEl.style.display = 'none';
          showBtn.textContent = 'Show Python';
        } else {
          codeEl.textContent = PY_CODE;
          codeEl.style.display = 'block';
          showBtn.textContent = 'Hide Python';
        }
      });

      function log(msg){ statusEl.textContent += msg + "\n"; }
      function setPhase(text, done=false){ phaseEl.textContent = text; spinnerEl.style.visibility = done ? 'hidden' : 'visible'; }

      async function ensurePyodide(){
        setPhase('Loading Python runtime…');
        const pyodide = await loadPyodide({ indexURL: 'https://cdn.jsdelivr.net/pyodide/v0.26.2/full/' });
        setPhase('Fetching core packages…');
        // Preload packages used below
        await pyodide.loadPackage(['numpy', 'pandas', 'matplotlib']);
        setPhase('Ready', true);
        rerunBtn.disabled = false;
        return pyodide;
      }

      async function runDemo(pyodide){
        statusEl.textContent = '';
        log('# Python environment ready');
        log('• pandas ' + pyodide.runPython('import pandas as pd; pd.__version__'));
        log('• numpy ' + pyodide.runPython('import numpy as np; np.__version__'));
        log('• matplotlib ' + pyodide.runPython('import matplotlib as m; m.__version__'));
        log('\nRunning chart code…');
        try {
          await pyodide.runPythonAsync(PY_CODE);
          log('Done. Chart updated.');
        } catch (err) {
          console.error(err);
          log('Error: ' + err);
        }
      }

      let pyodideReady = null;
      (async () => {
        pyodideReady = await ensurePyodide();
        await runDemo(pyodideReady);
      })();

      rerunBtn.addEventListener('click', async () => {
        if (!pyodideReady) return;
        await runDemo(pyodideReady);
      });
    </script>
  </body>
</html>
